package com.example.xuwsh.myBatisPlus.core.mapper;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.example.xuwsh.myBatisPlus.fun.ColumnService;
import com.example.xuwsh.myBatisPlus.utils.JuXiMapUtils;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.exceptions.TooManyResultsException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @Author: xuwsh
 * @Date: 2023/09/19/11:37
 * @Description:
 */
public interface JuXiBaseMapper<T> extends MPJBaseMapper<T> {
    int DEFAULT_BATCH_SIZE = 1000;

    //-------------新增-------------------------------

    /**
     * 批量新增
     *
     * @param entryList 实体类批量
     */
    void insertBatchSomeColumn(@Param(Constants.LIST) Collection<T> entryList);

    //-------------修改-------------------------------

    /**
     * 批量修改（修改的条数小于1000）
     *
     * @param entryList 实体类批量
     */
    default void updateByIdList(@Param(Constants.LIST) Collection<T> entryList) {
        updateByIdList(entryList, DEFAULT_BATCH_SIZE);
    }

    /**
     * 批量修改（修改的条数大于等于1000）
     *
     * @param entryList 实体类批量
     * @param size      批量条数
     */
    default void updateByIdList(@Param(Constants.LIST) Collection<T> entryList, int size) {
        Db.updateBatchById(entryList, size);
    }

    /**
     * 根据条件更新实体类
     *
     * @param entry
     * @param column
     * @param value
     */
    default void updateEntryEq(T entry, SFunction<T, ?> column, Object value) {
        String filed = getColumn(column);
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq(filed, value);
        update(entry, updateWrapper);
    }

    /**
     * 根据条件更新实体类
     *
     * @param entry
     * @param column
     * @param value
     * @param column1
     * @param value1
     */
    default void updateEntryEq(T entry, SFunction<T, ?> column, Object value, SFunction<T, ?> column1, Object value1) {
        String filed = getColumn(column);
        String filed1 = getColumn(column1);
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq(filed, value).eq(filed1, value1);
        update(entry, updateWrapper);
    }

    /**
     * 更新的时候，存在多个列校验
     *
     * @param entry
     * @param juXiMapUtils
     */
    default void updateEntryEq(T entry, JuXiMapUtils<T> juXiMapUtils) {
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        getEqUpdateWrapper(updateWrapper, juXiMapUtils);
        update(entry, updateWrapper);
    }

    /**
     * 根据某个列的值更新指定字段值
     *
     * @param juXiMapUtils
     * @param column
     * @param value
     */
    default void updateFiledEq(JuXiMapUtils<T> juXiMapUtils, SFunction<T, ?> column, Object value) {
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        getSetUpdateWrapper(updateWrapper, juXiMapUtils);
        String filed = getColumn(column);
        updateWrapper.eq(filed, value);
        update(null, updateWrapper);
    }

    /**
     * 根据某个列的值更新指定字段值
     *
     * @param juXiMapUtils
     * @param column
     * @param values
     */
    default void updateFiledIn(JuXiMapUtils<T> juXiMapUtils, SFunction<T, ?> column, Object... values) {
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        getSetUpdateWrapper(updateWrapper, juXiMapUtils);
        String filed = getColumn(column);
        updateWrapper.in(filed, values);
        update(null, updateWrapper);
    }

    /**
     * 根据某个列的值更新指定字段值
     *
     * @param juXiMapUtils
     * @param column
     * @param values
     */
    default void updateFiledIn(JuXiMapUtils<T> juXiMapUtils, SFunction<T, ?> column, Collection<?> values) {
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        getSetUpdateWrapper(updateWrapper, juXiMapUtils);
        String filed = getColumn(column);
        updateWrapper.in(filed, values);
        update(null, updateWrapper);
    }

    /**
     * 根据某个列的值更新指定字段值
     *
     * @param setJuXiMap 更新字段的map
     * @param eqJuXiMap  条件相等map
     * @param column     in 条件的列
     * @param values     in 条件的值
     */
    default void updateFiledInAndEq(JuXiMapUtils<T> setJuXiMap, JuXiMapUtils<T> eqJuXiMap, SFunction<T, ?> column, Collection<?> values) {
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        getSetUpdateWrapper(updateWrapper, setJuXiMap);
        getEqUpdateWrapper(updateWrapper, eqJuXiMap);
        String filed = getColumn(column);
        updateWrapper.in(filed, values);
        update(null, updateWrapper);
    }

    /**
     * 根据某列的数据多条进行更新
     *
     * @param entry
     * @param column
     * @param values
     */
    default void updateIn(T entry, SFunction<T, ?> column, Collection<?> values) {
        String filed = getColumn(column);
        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in(filed, values);
        update(entry, updateWrapper);
    }

    /**
     * 批量修改插入(条数小于1000)
     *
     * @param entryList 批量修改的实体类
     * @deprecated : 如果传入oid，则修改，否则新增
     */
    default void saveOrUpdateBatch(Collection<T> entryList) {
        saveOrUpdateBatch(entryList, DEFAULT_BATCH_SIZE);
    }

    /**
     * 批量修改插入(条数大于等于1000)
     *
     * @param entryList 批量修改的实体类
     * @param size      批量大小
     */
    default void saveOrUpdateBatch(Collection<T> entryList, int size) {
        Db.saveOrUpdateBatch(entryList, size);
    }

    //-------------删除-------------------------------

    /**
     * 根据某列的值进行删除
     *
     * @param column
     * @param value
     */
    default void delete(SFunction<T, ?> column, Object value) {
        String filed = getColumn(column);
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(filed, value);
        delete(queryWrapper);
    }

    /**
     * 根据某列的值进行删除
     *
     * @param column
     * @param value
     * @param column1
     * @param value1
     */
    default void delete(SFunction<T, ?> column, Object value, SFunction<T, ?> column1, Object value1) {
        String filed = getColumn(column);
        String filed1 = getColumn(column1);
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(filed, value).eq(filed1, value1);
        delete(queryWrapper);
    }

    /**
     * 如果删除存在多个
     *
     * @param juXiMapUtils
     */
    default void delete(JuXiMapUtils<T> juXiMapUtils) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        getEqQueryWrapper(queryWrapper, juXiMapUtils);
        delete(queryWrapper);
    }

    /**
     * 根据某列多个值进行删除
     *
     * @param column
     * @param values
     */
    default void delete(SFunction<T, ?> column, Collection<?> values) {
        String filed = getColumn(column);
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.in(filed, values);
        delete(queryWrapper);
    }

    //-------------查询-------------------------------

    /**
     * 查询一条数据
     *
     * @param column 列名，可以使用函数接口
     * @param value  需要查询的值
     * @return 返回查询结果
     */
    default T selectOne(SFunction<T, ?> column, Object value) {
        try {
            return selectOne(column, value, true);
        } catch (RuntimeException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 查询一条数据
     *
     * @param column
     * @param value
     * @param column1
     * @param value1
     * @return
     */
    default T selectOne(SFunction<T, ?> column, Object value, SFunction<T, ?> column1, Object value1) {
        try {
            return selectOne(column, value, column1, value1, true);
        } catch (RuntimeException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 查询一条数据
     *
     * @param column
     * @param value
     * @param column1
     * @param value1
     * @param column2
     * @param value2
     * @return
     */
    default T selectOne(SFunction<T, ?> column, Object value, SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Object value2) {
        try {
            return selectOne(column, value, column1, value1, column2, value2, true);
        } catch (RuntimeException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 查询到列数据超过3条需要使用map传参
     *
     * @param juXiMapUtils
     * @return
     */
    default T selectOne(JuXiMapUtils<T> juXiMapUtils) {
        try {
            return selectOne(juXiMapUtils, true);
        } catch (TooManyResultsException e) {
            throw new RuntimeException("您所要查询的数据不是唯一，存在多条数据");
        }
    }

    /**
     * 查询一条数据
     *
     * @param column  列名，可以使用函数接口
     * @param value   需要查询的值
     * @param throwEx 如果存在多条数据，是否需要抛出异常，如果不需要则返回第一条数据，如果需要，直接抛出异常
     * @return 返回查询结果
     */
    default T selectOne(SFunction<T, ?> column, Object value, boolean throwEx) {
        try {
            String filed = getColumn(column);
            QueryWrapper<T> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(filed, value);
            return MPJBaseMapper.super.selectOne(queryWrapper, throwEx);
        } catch (TooManyResultsException e) {
            throw new RuntimeException(String.format("%s,%s", value, "不是唯一，存在多条数据"));
        }
    }

    /**
     * 查询一条数据
     *
     * @param column
     * @param value
     * @param column1
     * @param value1
     * @param throwEx
     * @return
     */
    default T selectOne(SFunction<T, ?> column, Object value, SFunction<T, ?> column1, Object value1, boolean throwEx) {
        try {
            String filed = getColumn(column);
            String filed1 = getColumn(column1);
            QueryWrapper<T> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(filed, value).eq(filed1, value1);
            return MPJBaseMapper.super.selectOne(queryWrapper, throwEx);
        } catch (TooManyResultsException e) {
            throw new RuntimeException(String.format("%s,%s", value, "不是唯一，存在多条数据"));
        }
    }

    /**
     * 查询一条数据
     *
     * @param column
     * @param value
     * @param column1
     * @param value1
     * @param column2
     * @param value2
     * @param throwEx
     * @return
     */
    default T selectOne(SFunction<T, ?> column, Object value, SFunction<T, ?> column1, Object value1, SFunction<T, ?> column2, Object value2, boolean throwEx) {
        try {
            String filed = getColumn(column);
            String filed1 = getColumn(column1);
            String filed2 = getColumn(column2);
            QueryWrapper<T> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(filed, value).eq(filed1, value1).eq(filed2, value2);
            return MPJBaseMapper.super.selectOne(queryWrapper, throwEx);
        } catch (TooManyResultsException e) {
            throw new RuntimeException(String.format("%s,%s", value, "不是唯一，存在多条数据"));
        }
    }

    /**
     * 查询数据的列超过3个，使用map传参
     *
     * @param juXiMapUtils
     * @param throwEx
     * @return
     */
    default T selectOne(JuXiMapUtils<T> juXiMapUtils, boolean throwEx) {
        try {
            QueryWrapper<T> queryWrapper = new QueryWrapper<>();
            getEqQueryWrapper(queryWrapper, juXiMapUtils);
            return MPJBaseMapper.super.selectOne(queryWrapper, throwEx);
        } catch (TooManyResultsException e) {
            throw new RuntimeException("您所要查询的数据不是唯一，存在多条数据");
        }
    }

    /**
     * 是否存在数据
     *
     * @param column
     * @param value
     * @return
     */
    default boolean exists(SFunction<T, ?> column, Object value) {
        String filed = getColumn(column);
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(filed, value);
        return MPJBaseMapper.super.exists(queryWrapper);
    }

    /**
     * 是否存在数据
     *
     * @param column
     * @param value
     * @param column1
     * @param value1
     * @return
     */
    default boolean exists(SFunction<T, ?> column, Object value, SFunction<T, ?> column1, Object value1) {
        String filed = getColumn(column);
        String filed1 = getColumn(column1);
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(filed, value).eq(filed1, value1);
        return MPJBaseMapper.super.exists(queryWrapper);
    }

    /**
     * 是否存在数据 查询列超过两条
     *
     * @param juXiMapUtils
     * @return
     */
    default boolean exists(JuXiMapUtils<T> juXiMapUtils) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        getEqQueryWrapper(queryWrapper, juXiMapUtils);
        return MPJBaseMapper.super.exists(queryWrapper);
    }


    /**
     * 查询记录总数
     *
     * @param column 列名
     * @param value  列值
     * @return 返回结果
     */
    default Long selectCount(SFunction<T, ?> column, Object value) {
        String filed = getColumn(column);
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(filed, value);
        return selectCount(queryWrapper);
    }

    /**
     * 查询记录总数
     *
     * @param column
     * @param value
     * @param column1
     * @param value1
     * @return
     */
    default Long selectCount(SFunction<T, ?> column, Object value, SFunction<T, ?> column1, Object value1) {
        String filed = getColumn(column);
        String filed1 = getColumn(column1);
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(filed, value).eq(filed1, value1);
        return selectCount(queryWrapper);
    }

    /**
     * 查询记录总数
     *
     * @param juXiMapUtils 查询数据列超过两个
     * @return
     */
    default Long selectCount(JuXiMapUtils<T> juXiMapUtils) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        getEqQueryWrapper(queryWrapper, juXiMapUtils);
        return selectCount(queryWrapper);
    }

    /**
     * 查询所有
     *
     * @return
     */
    default List<T> selectList() {
        return selectList(new QueryWrapper<>());
    }

    /**
     * 根据一个入参信息查询数据
     *
     * @param column
     * @param value
     * @return
     */
    default List<T> selectList(SFunction<T, ?> column, Object value) {
        String filed = getColumn(column);
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(filed, value);
        return selectList(queryWrapper);
    }

    /**
     * 根据 两个入参查询数据
     *
     * @param column
     * @param value
     * @param column1
     * @param value1
     * @return
     */
    default List<T> selectList(SFunction<T, ?> column, Object value, SFunction<T, ?> column1, Object value1) {
        String filed = getColumn(column);
        String filed1 = getColumn(column1);
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(filed, value).eq(filed1, value1);
        return selectList(queryWrapper);
    }

    /**
     * 查询数据
     *
     * @param juXiMapUtils
     * @return
     */
    default List<T> selectList(JuXiMapUtils<T> juXiMapUtils) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        getEqQueryWrapper(queryWrapper, juXiMapUtils);
        return selectList(queryWrapper);
    }

    /**
     * 查询数据存在目标值
     *
     * @param column
     * @param values 值是多个
     * @return
     */
    default List<T> selectListIn(SFunction<T, ?> column, Object... values) {
        if (ObjectUtil.hasEmpty(values)) {
            return new ArrayList<>();
        }
        String filed = getColumn(column);
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.in(filed, values);
        return selectList(queryWrapper);
    }

    /**
     * 查询数据不存在目标值
     *
     * @param column
     * @param values
     * @return
     */
    default List<T> selectListNotIn(SFunction<T, ?> column, Object... values) {
        if (ObjectUtil.hasEmpty(values)) {
            return new ArrayList<>();
        }
        String filed = getColumn(column);
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.notIn(filed, values);
        return selectList(queryWrapper);
    }

    /**
     * 查询数据存在目标值
     *
     * @param column
     * @param values 值是数组
     * @return
     */
    default List<T> selectListIn(SFunction<T, ?> column, Collection<?> values) {
        if (CollectionUtils.isEmpty(values)) {
            return new ArrayList<>();
        }
        String filed = getColumn(column);
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.in(filed, values);
        return selectList(queryWrapper);
    }

    /**
     * 查询多个列In的条件
     *
     * @param juXiMapUtils
     * @return
     */
    default List<T> selectListIn(JuXiMapUtils<T> juXiMapUtils) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        getInQueryWrapper(queryWrapper, juXiMapUtils, Boolean.TRUE);
        return selectList(queryWrapper);
    }


    /**
     * 查询数据不存在目标值
     *
     * @param column
     * @param values
     * @return
     */
    default List<T> selectListNotIn(SFunction<T, ?> column, Collection<?> values) {
        if (CollectionUtils.isEmpty(values)) {
            return new ArrayList<>();
        }
        String filed = getColumn(column);
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.notIn(filed, values);
        return selectList(queryWrapper);
    }

    /**
     * 查询多个列不存在
     *
     * @param juXiMapUtils
     * @return
     */
    default List<T> selectListNotIn(JuXiMapUtils<T> juXiMapUtils) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        getInQueryWrapper(queryWrapper, juXiMapUtils, Boolean.FALSE);
        return selectList(queryWrapper);
    }

    /**
     * 查询某个列的值在某个区间数据
     *
     * @param column 列名
     * @param lValue 大于等于某个值
     * @param gValue 小于等于某个值
     * @return
     */
    default List<T> selectListRange(SFunction<T, ?> column, Object lValue, Object gValue) {
        if (ObjectUtil.isEmpty(lValue) && ObjectUtil.isEmpty(gValue)) {
            return new ArrayList<>();
        }
        String filed = getColumn(column);
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.ge(filed, lValue).le(filed, gValue);
        return selectList(queryWrapper);
    }

    /**
     * map类型Query数据做处理
     *
     * @param juXiMapUtils
     * @return
     */
    default void getEqQueryWrapper(QueryWrapper<T> queryWrapper, JuXiMapUtils<T> juXiMapUtils) {
        Map<String, Object> map = juXiMapUtils.getMap();
        for (Map.Entry<String, Object> s : map.entrySet()) {
            String key = s.getKey();
            Object value = s.getValue();
            queryWrapper.eq(key, value);
        }
    }

    /**
     * map类型Update数据做处理
     *
     * @param juXiMapUtils
     * @return
     */
    default void getEqUpdateWrapper(UpdateWrapper<T> updateWrapper, JuXiMapUtils<T> juXiMapUtils) {
        Map<String, Object> map = juXiMapUtils.getMap();
        for (Map.Entry<String, Object> s : map.entrySet()) {
            String key = s.getKey();
            Object value = s.getValue();
            updateWrapper.eq(key, value);
        }
    }

    /**
     * map类型Update数据做处理
     *
     * @param updateWrapper
     * @param juXiMapUtils
     * @return
     */
    default void getSetUpdateWrapper(UpdateWrapper<T> updateWrapper, JuXiMapUtils<T> juXiMapUtils) {
        Map<String, Object> map = juXiMapUtils.getMap();
        for (Map.Entry<String, Object> s : map.entrySet()) {
            String key = s.getKey();
            Object value = s.getValue();
            updateWrapper.set(key, value);
        }
    }

    /**
     * map类型数据做处理
     *
     * @param juXiMapUtils
     * @param flag
     * @return
     */
    default void getInQueryWrapper(QueryWrapper<T> queryWrapper, JuXiMapUtils<T> juXiMapUtils, Boolean flag) {
        Map<String, Object> map = juXiMapUtils.getMap();
        for (Map.Entry<String, Object> s : map.entrySet()) {
            String key = s.getKey();
            Collection<?> value = (Collection<?>) s.getValue();
            if (flag) {
                queryWrapper.in(key, value);
            } else {
                queryWrapper.notIn(key, value);
            }
        }
    }

    /**
     * 将函数式的入参转换为String
     *
     * @param column
     * @return
     */
    default String getColumn(SFunction<T, ?> column) {
        ColumnService<T> columnService = new ColumnService<>();
        return columnService.getFiled(column);
    }
}
